/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.modules.biz.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import me.zhengjie.modules.biz.domain.*;
import me.zhengjie.modules.biz.repository.CabinetRepository;
import me.zhengjie.modules.biz.repository.HazardousChemicalsRepository;
import me.zhengjie.modules.biz.repository.RefrigeratorRepository;
import me.zhengjie.modules.biz.service.dto.HazardousChemicalsDto;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.repository.UserRepository;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.biz.repository.HazardousChemicalsChangeRecordRepository;
import me.zhengjie.modules.biz.service.HazardousChemicalsChangeRecordService;
import me.zhengjie.modules.biz.service.dto.HazardousChemicalsChangeRecordDto;
import me.zhengjie.modules.biz.service.dto.HazardousChemicalsChangeRecordQueryCriteria;
import me.zhengjie.modules.biz.service.mapstruct.HazardousChemicalsChangeRecordMapper;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;

import java.lang.System;
import java.util.*;
import java.io.IOException;
import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Admin
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2023-03-09
 **/
@Service
@RequiredArgsConstructor
public class HazardousChemicalsChangeRecordServiceImpl implements HazardousChemicalsChangeRecordService {

    private final HazardousChemicalsChangeRecordRepository hazardousChemicalsChangeRecordRepository;
    private final HazardousChemicalsChangeRecordMapper hazardousChemicalsChangeRecordMapper;
    private final HazardousChemicalsRepository hazardousChemicalsRepository;
    private final CabinetRepository cabinetRepository;
    private final UserRepository userRepository;

    @Override
    public Map<String, Object> queryAll(HazardousChemicalsChangeRecordQueryCriteria criteria, Pageable pageable) {

        Specification<HazardousChemicalsChangeRecord> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (criteria.getName() != null) {
                predicates.add(criteriaBuilder.like(root.get("name"), "%" + criteria.getName() + "%"));
            }
            if (criteria.getNumber() != null) {
                predicates.add(criteriaBuilder.equal(root.get("number"), criteria.getNumber()));
            }
            if (criteria.getBatchNumber() != null) {
                predicates.add(criteriaBuilder.equal(root.get("batchNumber"), criteria.getBatchNumber()));
            }
            if (criteria.getIngredientData() != null) {
                predicates.add(criteriaBuilder.like(root.get("ingredientData"), "%" + criteria.getIngredientData() + "%"));
            }
            if (criteria.getCreatedAt() != null) {
                predicates.add(criteriaBuilder.between(root.get("createdAt"), criteria.getCreatedAt().get(0), criteria.getCreatedAt().get(1)));
            }
            if (criteria.getState() != null) {
                predicates.add(criteriaBuilder.equal(root.get("state"), criteria.getState()));
            }
            if (criteria.getType() != null) {
                predicates.add(criteriaBuilder.equal(root.get("type"), criteria.getType()));
            }
            if (criteria.getUserId() != null) {
                predicates.add(criteriaBuilder.equal(root.get("userId"), criteria.getUserId()));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };


        Page<HazardousChemicalsChangeRecord> page = hazardousChemicalsChangeRecordRepository.findAll(specification, pageable);
        Page<HazardousChemicalsChangeRecordDto> dto = page.map(hazardousChemicalsChangeRecordMapper::toDto);
        List<HazardousChemicalsChangeRecordDto> resultDto = dto.getContent();
        for (HazardousChemicalsChangeRecordDto hazardousChemicalsChangeRecordDto : resultDto) {
            if (hazardousChemicalsChangeRecordDto.getLqNumber() == null){
                hazardousChemicalsChangeRecordDto.setLqNumber((float) 0);
            }
            if (hazardousChemicalsChangeRecordDto.getGhNumber() == null){
                hazardousChemicalsChangeRecordDto.setGhNumber((float) 0);
            }
            if (hazardousChemicalsChangeRecordDto.getUsedNumber() == null){
                hazardousChemicalsChangeRecordDto.setUsedNumber((float) 0);
            }
//            Lab lab = labRepository.findById(hazardousChemicalsDto.getLabId()).orElseGet(Lab::new);

            HazardousChemicals hazardousChemicals = hazardousChemicalsRepository
                    .findById(hazardousChemicalsChangeRecordDto.getHcId()).orElseGet(HazardousChemicals::new);

//            hazardousChemicalsDto.setLabName(lab.getName());
            if (hazardousChemicals.getCabinetId() != null && hazardousChemicalsChangeRecordDto.getType() == 2) {//标准物质时type为2
                Cabinet cabinet = cabinetRepository.findById(hazardousChemicals.getCabinetId()).orElseGet(Cabinet::new);
                if (cabinet.getId() != null) {
                    hazardousChemicalsChangeRecordDto.setCabinetName(cabinet.getName());
                }
            } else {
                hazardousChemicalsChangeRecordDto.setCabinetName("-");
            }
//            Cabinet cabinet = cabinetRepository.findById(hazardousChemicalsDto.getCabinetId()).orElseGet(Cabinet::new);
//            hazardousChemicalsDto.setCabinetName(cabinet.getName());
            HazardousChemicals hc = hazardousChemicalsRepository.findById(hazardousChemicalsChangeRecordDto.getHcId()).orElseGet(HazardousChemicals::new);
            if (Objects.nonNull(hc.getUnit())) {
                hazardousChemicalsChangeRecordDto.setUnit(hc.getUnit());
            }

            User user = userRepository.findById(Convert.toLong(hazardousChemicalsChangeRecordDto.getUserId())).orElseGet(User::new);
            if (Objects.nonNull(user.getUsername())) {
                hazardousChemicalsChangeRecordDto.setUserName(user.getUsername());
            }
        }
        return PageUtil.toPage(dto);//list中的对象是引用传递的，因此上面修改resultDto的一些属性值，对应的dto中的值也会被修改
    }

    @Override
    public List<HazardousChemicalsChangeRecordDto> queryAll(HazardousChemicalsChangeRecordQueryCriteria criteria) {
        Specification<HazardousChemicalsChangeRecord> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (criteria.getName() != null) {
                predicates.add(criteriaBuilder.like(root.get("name"), "%" + criteria.getName() + "%"));
            }
            if (criteria.getNumber() != null) {
                predicates.add(criteriaBuilder.equal(root.get("number"), criteria.getNumber()));
            }
            if (criteria.getBatchNumber() != null) {
                predicates.add(criteriaBuilder.equal(root.get("batchNumber"), criteria.getBatchNumber()));
            }
            if (criteria.getIngredientData() != null) {
                predicates.add(criteriaBuilder.like(root.get("ingredientData"), "%" + criteria.getIngredientData() + "%"));
            }
            if (criteria.getCreatedAt() != null) {
                predicates.add(criteriaBuilder.between(root.get("createdAt"), criteria.getCreatedAt().get(0), criteria.getCreatedAt().get(1)));
            }
            if (criteria.getState() != null) {
                predicates.add(criteriaBuilder.equal(root.get("state"), criteria.getState()));
            }
            if (criteria.getType() != null) {
                predicates.add(criteriaBuilder.equal(root.get("type"), criteria.getType()));
            }
            query.where(predicates.toArray(new Predicate[0]));
            if (criteria.getType() == 2) {
                query.orderBy(criteriaBuilder.asc(root.get("name")), criteriaBuilder.asc(root.get("batchNumber")));
            }

            return query.getRestriction();
        };

        List<HazardousChemicalsChangeRecord> hazardousChemicalsChangeRecordList = hazardousChemicalsChangeRecordRepository.findAll(specification);
        List<HazardousChemicalsChangeRecordDto> hazardousChemicalsChangeRecordDtoList = hazardousChemicalsChangeRecordMapper.toDto(hazardousChemicalsChangeRecordList);
        for (HazardousChemicalsChangeRecordDto hazardousChemicalsChangeRecordDto : hazardousChemicalsChangeRecordDtoList) {
            HazardousChemicals hazardousChemicals = hazardousChemicalsRepository.findById(hazardousChemicalsChangeRecordDto.getHcId()).orElseGet(HazardousChemicals::new);
            if (hazardousChemicals.getId() != null) {
                Cabinet cabinet = cabinetRepository.findById(hazardousChemicals.getCabinetId()).orElseGet(Cabinet::new);
                if (cabinet.getId() != null) {
                    hazardousChemicalsChangeRecordDto.setCabinetName(cabinet.getName());
                }
            }
            HazardousChemicals hc = hazardousChemicalsRepository.findById(hazardousChemicalsChangeRecordDto.getHcId()).orElseGet(HazardousChemicals::new);
            if (hc.getId() != null) {
                hazardousChemicalsChangeRecordDto.setUnit(hc.getUnit());
            }

            User user = userRepository.findById(Convert.toLong(hazardousChemicalsChangeRecordDto.getUserId())).orElseGet(User::new);
            if (Objects.nonNull(user.getUsername())) {
                hazardousChemicalsChangeRecordDto.setUserName(user.getUsername());
            }
        }
        return hazardousChemicalsChangeRecordDtoList;
    }

    @Override
    @Transactional
    public HazardousChemicalsChangeRecordDto findById(Integer id) {
        HazardousChemicalsChangeRecord hazardousChemicalsChangeRecord = hazardousChemicalsChangeRecordRepository.findById(id).orElseGet(HazardousChemicalsChangeRecord::new);
        ValidationUtil.isNull(hazardousChemicalsChangeRecord.getId(), "HazardousChemicalsChangeRecord", "id", id);
        return hazardousChemicalsChangeRecordMapper.toDto(hazardousChemicalsChangeRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HazardousChemicalsChangeRecordDto create(HazardousChemicalsChangeRecord resources) {
//        if (resources.getState() == 1){
//            resources.setGhNumber(resources.getDetailNumber());
//        }else if (resources.getState() == 2){
//            resources.setLqNumber(resources.getDetailNumber());
//        }else if (resources.getState() == 3){
//            //1.根据用户id和化学试剂id 查询出该用户最近领取的该试剂的记录（按照时间排序最近一次优先）
//            List<HazardousChemicalsChangeRecord> list = hazardousChemicalsChangeRecordRepository.getListByUserIdAndHcId(resources.getUserId(),resources.getHcId());
//            //2.判断领取量大于归还量即可进行计算
//            for (HazardousChemicalsChangeRecord hazardousChemicalsChangeRecord : list){
//                if (hazardousChemicalsChangeRecord.getLqNumber() >= resources.getGhNumber()){
//                    //符合条件，领取量减去归还量作为使用量赋值给resources
//                    resources.setUsedNumber(hazardousChemicalsChangeRecord.getLqNumber() - resources.getGhNumber());
//                    //计算完毕，更新上面那条hazardousChemicalsChangeRecord的归还状态（is_return = 0）
//                    hazardousChemicalsChangeRecordRepository.updateIsReturn(hazardousChemicalsChangeRecord.getId());
//                }
//                break;
//            }
//        }else {
//            resources.setLqNumber(resources.getDetailNumber());
//        }
        return hazardousChemicalsChangeRecordMapper.toDto(hazardousChemicalsChangeRecordRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(HazardousChemicalsChangeRecord resources) {
        HazardousChemicalsChangeRecord hazardousChemicalsChangeRecord = hazardousChemicalsChangeRecordRepository.findById(resources.getId()).orElseGet(HazardousChemicalsChangeRecord::new);
        ValidationUtil.isNull(hazardousChemicalsChangeRecord.getId(), "HazardousChemicalsChangeRecord", "id", resources.getId());
        hazardousChemicalsChangeRecord.copy(resources);
        hazardousChemicalsChangeRecordRepository.save(hazardousChemicalsChangeRecord);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            hazardousChemicalsChangeRecordRepository.deleteById(id);
        }
    }

    @Override
    public void exportEquipmentsChangeRecord(List<HazardousChemicalsChangeRecordDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (HazardousChemicalsChangeRecordDto hazardousChemicalsChangeRecord : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("名称", hazardousChemicalsChangeRecord.getName());
            String state = null;
            switch (hazardousChemicalsChangeRecord.getState()) {
                case 1:
                    state = "入库";
                    break;
                case 2:
                    state = "出库";
                    break;
                case 3:
                    state = "归还";
                    break;
                case 4:
                    state = "销库";
                    break;
            }
            map.put("类型", state);
            String unit = "";
            switch (hazardousChemicalsChangeRecord.getUnit()) {
                case 1:
                    unit = "个";
                    break;
                case 2:
                    unit = "台";
                    break;
                case 3:
                    unit = "套";
                    break;
            }
            map.put("数量", hazardousChemicalsChangeRecord.getAmount() + unit);
            map.put("时间", hazardousChemicalsChangeRecord.getCreatedAt());
            map.put("操作人", hazardousChemicalsChangeRecord.getUserName());

            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void exportMaterialsChangeRecord(List<HazardousChemicalsChangeRecordDto> queryAll, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (HazardousChemicalsChangeRecordDto hazardousChemicalsChangeRecord : queryAll) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("参数", hazardousChemicalsChangeRecord.getName());
            String state = null;
            switch (hazardousChemicalsChangeRecord.getState()) {
                case 1:
                    state = "入库";
                    break;
                case 2:
                    state = "出库";
                    break;
                case 3:
                    state = "归还";
                    break;
                case 4:
                    state = "销库";
                    break;
            }
            map.put("类型", state);
            map.put("数量", hazardousChemicalsChangeRecord.getAmount() + "瓶");
            map.put("实际量", hazardousChemicalsChangeRecord.getDetailNumber() + "ml");
            map.put("编号", hazardousChemicalsChangeRecord.getNumber());
            map.put("批号", hazardousChemicalsChangeRecord.getBatchNumber());
            map.put("基体", hazardousChemicalsChangeRecord.getMatrix());
            map.put("有效期", hazardousChemicalsChangeRecord.getExpirationDate());
            map.put("冰箱", hazardousChemicalsChangeRecord.getCabinetName());
            map.put("时间", hazardousChemicalsChangeRecord.getCreatedAt());
            map.put("操作人", hazardousChemicalsChangeRecord.getUserName());

            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void exportChemicalsChangeRecord(List<HazardousChemicalsChangeRecordDto> queryAll, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (HazardousChemicalsChangeRecordDto hazardousChemicalsChangeRecord : queryAll) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("名称", hazardousChemicalsChangeRecord.getName());
            String state = null;
            switch (hazardousChemicalsChangeRecord.getState()) {
                case 1:
                    state = "盘库入库";
                    break;
                case 2:
                    state = "领取";
                    break;
                case 3:
                    state = "归还";
                    break;
                case 4:
                    state = "销库";
                    break;
                case 5:
                    state = "盘库";
                    break;
            }
            String unit = hazardousChemicalsChangeRecord.getUnit() == 1 ? "L" : hazardousChemicalsChangeRecord.getUnit() == 3 ? "g" : "ml";
            map.put("类型", state);
            map.put("数量", hazardousChemicalsChangeRecord.getAmount() + "瓶");
            //map.put("实际量", hazardousChemicalsChangeRecord.getDetailNumber() + unit);
            if (hazardousChemicalsChangeRecord.getLqNumber() == null){
                map.put("领取量","/");
            }else {
                map.put("领取量", hazardousChemicalsChangeRecord.getLqNumber() + unit);
            }
            if (hazardousChemicalsChangeRecord.getGhNumber() == null){
                map.put("归还量","/");
            }else {
                map.put("归还量", hazardousChemicalsChangeRecord.getGhNumber() + unit);
            }
            if (hazardousChemicalsChangeRecord.getUsedNumber() == null){
                map.put("使用量","/");
            }else {
                map.put("使用量", hazardousChemicalsChangeRecord.getUsedNumber() + unit);
            }
            map.put("时间", hazardousChemicalsChangeRecord.getCreatedAt());
            map.put("操作人", hazardousChemicalsChangeRecord.getUserName());

            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}
